/*
 * This file is part of din.
 *
 * din is copyright (c) 2006 - 2012 S Jagannathan <jag@dinisnoise.org>
 * For more information, please visit http://dinisnoise.org
 *
 * din is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 2 of the License, or
 * (at your option) any later version.
 *
 * din is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * for more details.
 *
 * You should have received a copy of the GNU General Public License along
 * with din.  If not, see <http://www.gnu.org/licenses/>.
 *
*/

#include "widget.h"

#include <vector>

#include <fstream>
#include <string>
#include <sstream>

#include <iostream>

using namespace std;

extern int mousex, mouseyy;
extern int lmb, mmb, rmb;

widget* widget::focus = 0;

widget::widget (int left, int bottom, int right, int top) : extents (left, bottom, right, top), clr (1, 1, 1), movr (*this) {
	
	hover = 0;

	moveable = 0;

	posx = posy = 0;
	
	enable_ = 1;
	visible_ = 1;
		
	stringstream ss; ss << this; ss >> name;
	
}

int widget::handle_input () {
	if (inbox (extents, mousex, mouseyy)) hover = 1; else hover =  0;
	int mret = 0; if (moveable) mret = movr.handle_input ();
	return hover & mret ;
}

void widget::draw () {
	glColor3f (clr.r, clr.g, clr.b);
}

void widget::draw_bbox () {
	const box<int>& e = get_extents ();
	glBegin (GL_LINE_LOOP);
		glVertex2i (e.left, e.bottom);
		glVertex2i (e.right, e.bottom);
		glVertex2i (e.right, e.top);
		glVertex2i (e.left, e.top);
	glEnd ();
}

void widget::set_pos (int x, int y) {
	posx = x; 
	posy = y;
	set_extents (x, y, x + extents.width, y + extents.height);
}

void widget::get_pos (int& x, int& y) {
	x = posx;
	y = posy;
}

void widget::set_extents (int l, int b, int r, int t) {
	extents (l, b, r, t);
}

void widget::move (int dx, int dy) {
	
	// new position
	int x = posx + dx;
	int y = posy + dy;
	set_pos (x, y);
		
	// move children
	size_vw n = children.size ();
	if (n) for (size_vw i = 0; i < n; ++i) children[i]->move (dx, dy);

}

/*void widget::move_to (int x, int y) {
	int dx = x - posx, dy = y - posy;
	move (dx, dy);
}*/

void widget::show () {
	visible_ = 1;
	for (size_vw i = 0, j = children.size (); i < j; ++i) children[i]->show ();
}

void widget::hide () {
	visible_ = 0;
	for (size_vw i = 0, j = children.size (); i < j; ++i) children[i]->hide ();	
}

void widget::add_child (widget* w) {
	children.push_back (w);
}

void widget::add_screen (ui* scr) {
	screens.push_back (scr);
	for (vector<widget*>::size_type i = 0, j = children.size (); i < j; ++i) children[i]->add_screen (scr);
}

int widget::is_screen (ui* scr) {
	for (vector<ui*>::size_type i = 0, j = screens.size (); i < j; ++i) {
		ui* scri = screens[i];
		if ( (scr == scri) || (scri == 0)) return 1;
	}
	return 0;
}

void widget::save (ofstream& file) {
	file << name << ' ' << posx << ' ' << posy << endl;
}

mover::mover (widget& _w, int* _pmb) : w (_w){
	pmb = _pmb;
}

int mover::handle_input () {
	
	int ret = 0;
	int mb = *pmb;
	if (mb) {
		if (mb_clicked == 0) {
			if (move) {
				move = 0;
				widget::focus = 0;
				ret = 1;
			}
			else if (w.hovering()) { 
				move = 1;
				widget::focus = &w;
				prevx = mousex; 
				prevy = mouseyy;
				ret = 1;
			}
			mb_clicked = 1;
		}
	} else {
		if (move) {
			int dx = mousex - prevx, dy = mouseyy - prevy;
				w.move (dx, dy);
			prevx = mousex; prevy = mouseyy;
			ret = 1;
		}
		mb_clicked = 0;
	}
	
	return ret;
}
